// import { Component } from "vue"
import moment from 'moment'

const urlMatcher = /(\s|^)[^\s]+:\/\/[^\s]+(\s|$)/

type logHandler = (log: ComponentInstance[]) => void

export type ComponentInstance = {
  component: string,
  props: any
}

interface LogStyleInit {
  containerStyle?: string
  prefixStyle?: string
  messageStyle?: string
  containerClass?: string
  prefixClass?: string
  messageClass?: string
}

function logTextToHtmlLine(text: string): string {
  if (typeof(text) != 'string') {
    return `logTextToHtmlLine can only output string, you provide\n================================\n${text}\n================================\n`
  }
  let result = ''
  let restIndex = 0

  const maxLoop = 100
  let loopTime = 0
  while (restIndex < text.length && loopTime < maxLoop) {
    const rest = text.slice(restIndex)
    
    // find url
    const match = rest.match(urlMatcher)
    const breakIndex = match?.index

    // find
    if (match !== null && breakIndex !== undefined) {
      const preText = text.slice(restIndex, restIndex+breakIndex)
      result += preText
      const url = match[0].trim()
      result += ` <a href="${url}" target="_blank">${url}</a> `
      restIndex = restIndex+breakIndex+match[0].length
    }
    else {
      result += text.slice(restIndex)
      restIndex = text.length
    }

    loopTime += 1
  }

  if (loopTime >= maxLoop) {
    console.error('Logger: max loop exceeded in textToHtml')
    return text
  }

  return result
}

export class Logger {
  lines = [] as ComponentInstance[]

  handlers = [] as logHandler[]

  private _dispath() {
    for (const handler of this.handlers) {
      handler(this.lines)
    }
  }

  _log(t: string) {
    this.lines.push({
      component: 'HtmlLine',
      props: { html: t, }
    })
    this._dispath()
  }
  
  /**
   * 输出文本 - 附带链接识别功能
   * @param text 要输出的文本
   */
  logText(text:string) {
    const html = logTextToHtmlLine(text)
    this._log(html)
  }

  _develop(level: string, text: string, from?: string, styleInit?: LogStyleInit) {
    const pre = `${moment().format("YYYY-MM-DD HH:mm:ss")} - [${level}]${ from ? ` - ${from}` : '' } - `
    const txt = `\
<div class="log-container ${styleInit?.containerClass ?? ''}" style="${styleInit?.containerStyle ?? ''}">
  <div class="log-prefix ${styleInit?.prefixClass ?? ''}" style="${styleInit?.prefixStyle ?? ''}">${pre}</div>
  <div class="log-message ${styleInit?.messageClass ?? ''}" style="${styleInit?.messageStyle ?? ''}">${text}</div>
</div>
`
    this._log(txt)
  }

  debug(text: string, from?: string) {
    console.log(text, from)
    this._develop("debug", text, from)
  }

  error(text: string, from?: string) {
    console.error(text)
    this._develop("error", text, from, {
      containerClass: 'error-container',
      prefixClass: 'error-prefix',
      messageClass: 'error-message',
    })
  }

  critical(text: string, from?: string) {
    this.error(text, from)
    const _from = from ? `${from}: ` : ''
    throw new Error(`${_from}${text}`)
  }

  warn(text: string, from?: string) {
    console.warn(text)
    this._develop("warnning", text, from, {
      containerClass: 'warning-container',
      prefixClass: 'warning-prefix',
      messageClass: 'warning-message',
    })
  }

  success(text: string, from?: string) {
    this._develop("success", text, from, {
      containerClass: 'success-container',
      prefixClass: 'success-prefix',
      messageClass: 'success-message',
    })
  }
  

  onLog(handler: logHandler) {
    this.handlers.push(handler)
    // handler(this.lines)
  }
}

export const shell = new Logger()